home *** CD-ROM | disk | FTP | other *** search
-
- /* Written by Peter Ekberg, peda@lysator.liu.se */
-
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
-
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
-
- #ifdef HAVE_VALUES_H
- # include <values.h>
- #else
- # include <limits.h>
- # define MAXINT INT_MAX
- # define MAXLONG LONG_MAX
- #endif
-
- #include <stdlib.h>
- #include <math.h>
-
- #include "thrust_t.h"
- #include "things.h"
- #include "fast_gr.h"
- #include "graphics.h"
- #include "thrust.h"
-
- #ifdef HAVE_SOUND
- # include "soundIt.h"
-
- # define CHAN_1 0
- # define CHAN_2 1
- # define CHAN_3 2
- # define CHAN_4 3
-
- # define SND_BOOM 0
- # define SND_BOOM2 1
- # define SND_HARP 2
- # define SND_THRUST 3
- # define SND_ZERO 4
- #endif
-
- word nrthings=0;
- word nrsliders=0;
- word nrbarriers=0;
- word nrrestartpoints=0;
-
- bullet bullets[maxbullets];
- fragment fragments[maxfragments];
- thing things[maxthings];
- slider sliders[maxsliders];
- barrier barriers[maxbarriers];
- restartpoint restartpoints[maxrestartpoints];
-
- word powerplant;
- word ppx,ppy,ppcount; /* Power Plant variables */
- word ppblip;
-
- void
- newslider(x, y, type)
- int x, y, type;
- {
- sliders[nrsliders].x1=x;
- sliders[nrsliders].y1=y;
- sliders[nrsliders].type=type;
- sliders[nrsliders].dir=type%3;
- sliders[nrsliders].match=0;
- sliders[nrsliders].active=0;
- sliders[nrsliders++].next=NULL;
- }
-
- int
- majorbutton(int button)
- {
- if(((buttondata *)things[button].data)->major==-1)
- return(button);
- else
- return(((buttondata *)things[button].data)->major);
- }
-
- void
- newthing(int x, int y, int px, int py, int type, void *data)
- {
- int life;
-
- switch(type) {
- case 1: /* Fuel */
- life=140;
- break;
- default:
- life=2;
- }
- things[nrthings].alive=life;
- things[nrthings].x=x;
- things[nrthings].y=y;
- things[nrthings].px=px;
- things[nrthings].py=py;
- things[nrthings].type=type;
- things[nrthings].data=data;
- things[nrthings++].score=0;
- }
-
- void
- animatesliders(void)
- {
- slider *s=sliders;
- int i;
-
- for(i=0; i<nrsliders; i++, s++)
- if(s->active) {
- switch(s->stage) {
- case 0:
- if(!(s->count&7)) {
- switch(s->type) {
- case 2:
- if(s->count==0) {
- writeblock(s->x1-(s->count>>3), s->y1, 'x');
- writeblock(s->x1-(s->count>>3)-1, s->y1, 136);
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'q');
- }
- else if(s->count==8) {
- writeblock(s->x1-(s->count>>3), s->y1, 'w');
- writeblock(s->x1-(s->count>>3)-1, s->y1, 'r');
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'q');
- }
- else {
- writeblock(s->x1-(s->count>>3), s->y1, ' ');
- writeblock(s->x1-(s->count>>3)-1, s->y1, 'r');
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'q');
- }
- break;
- case 5:
- if(s->count==0) {
- writeblock(s->x1-(s->count>>3) , s->y1, 138);
- writeblock(s->x1-(s->count>>3)-1, s->y1, 139);
- }
- else if(s->count==8) {
- writeblock(s->x1-(s->count>>3) , s->y1, 141);
- writeblock(s->x1-(s->count>>3)-1, s->y1, 134);
- }
- else {
- writeblock(s->x1-(s->count>>3) , s->y1, 135);
- writeblock(s->x1-(s->count>>3)-1, s->y1, 134);
- }
- break;
- case 7:
- writeblock(s->x1+(s->count>>3), s->y1, 'y');
- break;
- case 8:
- writeblock(s->x1-(s->count>>3), s->y1, '|');
- break;
- case 10:
- writeblock(s->x1, s->y1+(s->count>>3), 129);
- break;
- case 11:
- writeblock(s->x1, s->y1-(s->count>>3), 128);
- break;
- }
- }
- else if(!(s->count&3)) {
- switch(s->type) {
- case 2:
- if(s->count==4) {
- writeblock(s->x1-(s->count>>3)-1, s->y1, 137);
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'n');
- }
- else {
- writeblock(s->x1-(s->count>>3)-1, s->y1, 'o');
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'n');
- }
- break;
- case 5:
- if(s->count==4) {
- writeblock(s->x1-(s->count>>3), s->y1, 133);
- writeblock(s->x1-(s->count>>3)-1, s->y1, 140);
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'u');
- }
- else if(s->count==12) {
- writeblock(s->x1-(s->count>>3), s->y1, 132);
- writeblock(s->x1-(s->count>>3)-1, s->y1, 'v');
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'u');
- }
- else {
- writeblock(s->x1-(s->count>>3), s->y1, ' ');
- writeblock(s->x1-(s->count>>3)-1, s->y1, 'v');
- writeblock(s->x1-(s->count>>3)-2, s->y1, 'u');
- }
- break;
- case 7:
- writeblock(s->x1+(s->count>>3), s->y1, ' ');
- break;
- case 8:
- writeblock(s->x1-(s->count>>3), s->y1, ' ');
- break;
- case 10:
- writeblock(s->x1, s->y1+(s->count>>3), ' ');
- break;
- case 11:
- writeblock(s->x1, s->y1-(s->count>>3), ' ');
- break;
- }
- }
- s->count++;
- if(s->count >= ((abs(s->x1-s->x2)+abs(s->y1-s->y2)+1) << 3)-1) {
- s->count=0;
- s->stage=1;
- }
- break;
- case 1:
- s->count++;
- if(s->count>500) {
- s->count=0;
- s->stage=2;
- }
- break;
- case 2:
- if(!(s->count&7)) {
- switch(s->type) {
- case 2:
- if(s->count>>3==s->x1-s->x2) {
- writeblock(s->x2+(s->count>>3)-1, s->y1, 136);
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'q');
- }
- else {
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'r');
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'q');
- }
- break;
- case 5:
- if(s->count>>3==s->x1-s->x2) {
- writeblock(s->x2+(s->count>>3) , s->y1, 138);
- writeblock(s->x2+(s->count>>3)-1, s->y1, 139);
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- else if(s->count>>3==s->x1-s->x2-1) {
- writeblock(s->x2+(s->count>>3) , s->y1, 141);
- writeblock(s->x2+(s->count>>3)-1, s->y1, 134);
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- else {
- writeblock(s->x2+(s->count>>3) , s->y1, 135);
- writeblock(s->x2+(s->count>>3)-1, s->y1, 134);
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- break;
- case 7:
- writeblock(s->x2-(s->count>>3), s->y1, 'y');
- break;
- case 8:
- writeblock(s->x2+(s->count>>3), s->y1, '|');
- break;
- case 10:
- writeblock(s->x1, s->y2-(s->count>>3), 129);
- break;
- case 11:
- writeblock(s->x1, s->y2+(s->count>>3), 128);
- break;
- }
- }
- else if(!(s->count&3)) {
- switch(s->type) {
- case 2:
- if(s->count>>3==s->x1-s->x2) {
- writeblock(s->x2+(s->count>>3) , s->y1, 'p');
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'p');
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- else if(s->count>>3==s->x1-s->x2-1) {
- writeblock(s->x2+(s->count>>3) , s->y1, 137);
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'n');
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- else {
- writeblock(s->x2+(s->count>>3) , s->y1, 'o');
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'n');
- writeblock(s->x2+(s->count>>3)-2, s->y1, 'p');
- }
- break;
- case 5:
- if(s->count>>3==s->x1-s->x2) {
- writeblock(s->x2+(s->count>>3) , s->y1, 'p');
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'p');
- }
- else if(s->count>>3==s->x1-s->x2-1) {
- writeblock(s->x2+(s->count>>3) , s->y1, 140);
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'u');
- }
- else {
- writeblock(s->x2+(s->count>>3) , s->y1, 'v');
- writeblock(s->x2+(s->count>>3)-1, s->y1, 'u');
- }
- break;
- case 7:
- writeblock(s->x2-(s->count>>3), s->y1, 'p');
- break;
- case 8:
- writeblock(s->x2+(s->count>>3), s->y1, 'p');
- break;
- case 10:
- writeblock(s->x1, s->y2-(s->count>>3), 'p');
- break;
- case 11:
- writeblock(s->x1, s->y2+(s->count>>3), 'p');
- break;
- }
- }
- s->count++;
- if(s->count >= ((abs(s->x1-s->x2)+abs(s->y1-s->y2)+1) << 3)-1)
- s->active=0;
- break;
- }
- }
- }
-
- void
- startupsliders(int button)
- {
- slider *s;
-
- s=((buttondata *)things[button].data)->sliders;
-
- while(s) {
- if(s->active) {
- switch(s->stage) {
- case 1:
- s->count=0;
- break;
- case 2:
- s->count=(((abs(s->x1-s->x2)+abs(s->y1-s->y2)+1) << 3)-1) - s->count-7;
- if(s->count<0)
- s->count=0;
- s->stage=0;
- break;
- default:
- break;
- }
- }
- else {
- #ifdef HAVE_SOUND
- if(play_sound)
- Snd_effect(SND_HARP, CHAN_3);
- #endif
- s->active=1;
- s->stage=0;
- s->count=0;
- }
- s=s->next;
- }
- }
-
- restartpoint *
- atbarrier(word bx, word by)
- {
- int i;
-
- for(i=0; i<nrbarriers; i++)
- if((barriers[i].x==bx) && (barriers[i].y==by))
- return(barriers[i].restart);
- return(NULL);
- }
-
- void
- deletething(thing *tp)
- {
- int tx, ty, i, j;
-
- tx=(*tp).px;
- ty=(*tp).py;
- (*tp).alive=0;
-
- switch((*tp).type)
- {
- case 1: /* Fuel */
- for(i=0; i<2; i++)
- for(j=0; j<2; j++)
- writeblock(tx+i, ty+j, 32);
- break;
- case 2: /* Power Plant */
- if(powerplant) {
- powerplant=0;
- countdown=1000;
- for(i=0; i<2; i++)
- for(j=0; j<2; j++)
- writeblock(tx+i, ty+j, 32);
- }
- if(countdown)
- (*tp).alive=1;
- else {
- killallthings();
- #ifdef HAVE_SOUND
- if(play_sound)
- Snd_effect(SND_BOOM2, CHAN_4);
- #endif
- for(i=0; i<3; i++)
- for(j=0; j<3; j++)
- writeblock(tx+i, ty+j, 32);
- explodething(tp);
- }
- break;
- case 3: /* Bunkers */
- writeblock(tx, ty, 32);
- writeblock(tx+1, ty, 32);
- writeblock(tx+2, ty, 32);
- writeblock(tx+2, ty+1, 32);
- break;
- case 4:
- writeblock(tx, ty+1, 32);
- writeblock(tx, ty, 32);
- writeblock(tx+1, ty, 32);
- writeblock(tx+2, ty, 32);
- break;
- case 5:
- writeblock(tx, ty+1, 32);
- writeblock(tx+1, ty+1, 32);
- writeblock(tx+2, ty+1, 32);
- writeblock(tx+2, ty, 32);
- break;
- case 6:
- writeblock(tx, ty, 32);
- writeblock(tx, ty+1, 32);
- writeblock(tx+1, ty+1, 32);
- writeblock(tx+2, ty+1, 32);
- break;
- case 7:
- case 8:
- writeblock(tx, ty, 32);
- writeblock(tx, ty+1, 32);
- break;
- }
- }
-
- void
- newbullet(word x, word y, int vx, int vy, word dir, int owner)
- {
- static word nr=0;
-
- #ifdef HAVE_SOUND
- if(play_sound)
- Snd_effect(SND_BOOM, CHAN_2);
- #endif
- bullets[nr].life=60;
- bullets[nr].x=x;
- bullets[nr].y=y;
- bullets[nr].vx=vx;
- bullets[nr].vy=vy;
- bullets[nr].dir=dir;
- bullets[nr++].owner=owner;
-
- if(nr==maxbullets)
- nr=0;
- }
-
- void
- movebullets(void)
- {
- int l;
- bullet *bulletptr;
-
- for(l=0, bulletptr=bullets; l<maxbullets; l++, bulletptr++)
- if((*bulletptr).life) {
- (*bulletptr).life--;
- (*bulletptr).x=((*bulletptr).x+(lenx<<6)+(*bulletptr).vx) % (lenx<<6);
- (*bulletptr).y=((*bulletptr).y+(leny<<6)-(*bulletptr).vy) % (leny<<6);
- }
- }
-
- word
- crashtype(word type)
- {
- switch(type) {
- case 1: /* Fuel */
- case 2: /* Power Plant */
- case 3: /* 3-6 Bunkers */
- case 4:
- case 5:
- case 6:
- case 7: /* 7-8 Buttons */
- case 8:
- return(4);
- }
- return(0);
- }
-
- int
- inloadcontact(int x, int y)
- {
- int dx, dy;
- int dist;
- int res=0;
- double angle;
- double sp, spr;
-
- dx=x-(loadbx<<3)-2;
- dy=(loadby<<3)-y+2;
- dist=dx*dx+dy*dy;
- if(dist<1024) {
- res=1-loadcontact;
- }
- else if(dist>=1024 && loadcontact) {
- loadcontact=0;
- loaded=1;
- alpha = atan2(dy, dx);
- angle = atan2(speedy, speedx) - alpha;
- sp=hypot(speedx, speedy);
- deltaalpha=sp*sin(angle)/2 * M_PI/262144;
- deltaalpha=min(deltaalpha, M_PI/16);
- deltaalpha=max(deltaalpha, -M_PI/16);
- spr=sp*cos(angle);
- speedx = spr*cos(alpha)/(1 + REL_MASS);
- speedy = spr*sin(alpha)/(1 + REL_MASS);
- }
- return(res);
- }
-
- int
- resonablefuel(int x, int y, int l)
- {
- thing *tp;
- int dx, dy;
-
- tp=&things[l];
- dx=x-(int)(*tp).x;
- dy=(int)(*tp).y-y;
- if(dx>(int)(lenx3>>1))
- dx=lenx3-dx;
- if(-dx>(int)(lenx3>>1))
- dx=-lenx3+dx;
- return(dx>-10 && dx<9 && dy>5 && dy<60);
- }
-
- int
- closestfuel(int x, int y)
- {
- word i, which=0;
- thing *thingptr;
- int dx, dy;
- int minimum=MAXINT, d;
- int hit=0;
-
- for(i=0, thingptr=things; i<nrthings; i++, thingptr++)
- if((*thingptr).type==1 && (*thingptr).alive>1) {
- dx=abs((int)x-(int)(*thingptr).x);
- dy=abs((int)y-(int)(*thingptr).y);
- if(dx>(lenx3>>1))
- dx-=lenx3;
- dy*=3;
- d=dx*dx+dy*dy;
- if(d<minimum) {
- minimum=d;
- which=i;
- hit=1;
- }
- }
- return(hit?which:-1);
- }
-
- int
- closestbutton(int x, int y)
- {
- word i, which=0;
- thing *thingptr;
- int dx, dy;
- int minimum=MAXINT, d;
- int hit=0;
-
- for(i=0, thingptr=things; i<nrthings; i++, thingptr++)
- if((*thingptr).type>=7 && (*thingptr).type<=8) {
- dx=abs((int)x-(int)(*thingptr).x);
- dy=abs((int)y-(int)(*thingptr).y);
- if(dx>(lenx>>1))
- dx-=lenx;
- d=dx*dx+dy*dy;
- if(d<minimum) {
- minimum=d;
- which=i;
- hit=1;
- }
- }
- return(hit?which:-1);
- }
-
- void
- hit(word x, word y, word crash, word owner)
- {
- word i, which=0;
- thing *thingptr;
- long dx, dy;
- long minimum=MAXLONG, d;
- int hit=0;
- int kill=1;
-
- for(i=0, thingptr=things; i<nrthings; i++, thingptr++)
- if((*thingptr).alive>0 && crashtype((*thingptr).type)==crash) {
- dx=(int)x-(int)(*thingptr).x;
- dy=(int)y-(int)(*thingptr).y;
- d=(long)dx*dx+(long)dy*dy;
- if(d<minimum) {
- minimum=d;
- which=i;
- hit=1;
- }
- }
- if(hit) {
- #ifdef HAVE_SOUND
- if(play_sound)
- Snd_effect(SND_BOOM2, CHAN_4);
- #endif
- explodething(&things[which]);
- }
- if(things[which].alive == 1) /* Can't kill a dying thing */
- hit=0;
- if(hit) {
- switch(things[which].type) {
- case 2:
- ppblip+=10;
- if(ppblip>100)
- things[which].alive=1; /* Dying */
- break;
- case 7: /* Cannot kill buttons */
- case 8:
- startupsliders(majorbutton(which));
- break;
- default:
- things[which].alive=1; /* Dying */
- break;
- }
- if(kill) {
- }
- if(owner)
- switch(things[which].type) {
- case 1:
- things[which].score=150;
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- things[which].score=750;
- break;
- }
- }
- }
-
- void
- bunkerfirebullet(thing *b)
- {
- int dir;
-
- dir=random()%16;
- switch((*b).type) {
- case 3:
- dir=(dir-3)&31;
- newbullet(((*b).x<<3)+14, ((*b).y<<3)-68,
- 32*cos(dir * M_PI/16), 32*sin(dir * M_PI/16),
- dir>>1, 0);
- break;
- case 4:
- dir=(dir+3)&31;
- newbullet(((*b).x<<3)-26, ((*b).y<<3)-68,
- 32*cos(dir * M_PI/16), 32*sin(dir * M_PI/16),
- dir>>1, 0);
- break;
- case 5:
- dir=(dir-14)&31;
- newbullet(((*b).x<<3)+14, ((*b).y<<3)+44,
- 32*cos(dir * M_PI/16), 32*sin(dir * M_PI/16),
- dir>>1, 0);
- break;
- case 6:
- dir=(dir+12)&31;
- newbullet(((*b).x<<3)-26, ((*b).y<<3)+44,
- 32*cos(dir * M_PI/16), 32*sin(dir * M_PI/16),
- dir>>1, 0);
- break;
- }
- }
-
- void
- bunkerfirebullets(void)
- {
- int l;
- thing *thingptr;
-
- for(l=0, thingptr=things; l<nrthings; l++, thingptr++)
- if((*thingptr).alive)
- if((*thingptr).type>2 && (*thingptr).type<7)
- if(!(random()%256))
- bunkerfirebullet(thingptr);
- }
-
- int
- killdyingthings(void)
- {
- int l;
- thing *thingptr;
- int res;
-
- res=0;
- for(l=0, thingptr=things; l<nrthings; l++, thingptr++)
- if((*thingptr).alive==1) {
- deletething(thingptr);
- res+=(*thingptr).score;
- }
-
- return(res);
- }
-
- void
- killallthings(void)
- {
- thing *thingptr;
- int l;
-
- for(l=0, thingptr=things; l<nrthings; l++, thingptr++) {
- if((*thingptr).alive > 1) {
- (*thingptr).alive=1;
- deletething(thingptr);
- explodething(thingptr);
- }
- }
- }
-
- void
- newfragment(word x, word y)
- {
- static word nr=0;
- int dir;
- int speed;
-
- dir=random()%32;
- speed=random()%48+16;
- fragments[nr].life=90-speed;
- fragments[nr].x=x;
- fragments[nr].y=y;
- fragments[nr].vx=speed*cos(dir * M_PI/16)/8;
- fragments[nr++].vy=speed*sin(dir * M_PI/16)/8;
-
- if(nr==maxfragments)
- nr=0;
- }
-
- void
- explodething(thing *thingptr)
- {
- int i;
-
- for(i=0; i<30; i++) {
- newfragment((thingptr->x<<3)-30+random()%61,
- (thingptr->y<<3)-30+random()%61);
- }
- }
-
- void
- explodeship(void)
- {
- int i;
-
- for(i=0; i<50; i++) {
- newfragment((x+((154+shipdx)<<3)+random()%61)%(lenx3<<3),
- (y+(( 82+shipdy)<<3)+random()%61)%(leny3<<3));
- if(loaded)
- newfragment((x+((161-(int)((252-loadpoint)*cos(alpha)/7.875))<<3)
- +random()%61)%(lenx3<<3),
- (y+(( 89+(int)((252-loadpoint)*sin(alpha)/7.875))<<3)
- +random()%61)%(leny3<<3));
- }
- }
-
- void
- movefragments(void)
- {
- int l;
- fragment *fragmentptr;
-
- for(l=0, fragmentptr=&fragments[0]; l<maxfragments; l++, fragmentptr++)
- if((*fragmentptr).life>0) {
- (*fragmentptr).life--;
- (*fragmentptr).x=((*fragmentptr).x+(lenx<<6)+(*fragmentptr).vx)
- % (lenx<<6);
- (*fragmentptr).y=((*fragmentptr).y+(leny<<6)-(*fragmentptr).vy)
- % (leny<<6);
- }
- }
-
- word
- livefragments(void)
- {
- int l;
- fragment *fragmentptr;
-
- for(l=0, fragmentptr=&fragments[0]; l<maxfragments; l++, fragmentptr++)
- if(fragmentptr->life>0)
- return(1);
- return(0);
- }
-